<template>
  <div class="app-container">
    <div class="search-container">
      <el-form v-show="showSearch" ref="queryParamsRef" :inline="true" :model="queryParams">
        <el-form-item label="菜单名称" prop="menuName">
          <el-input v-model="queryParams.menuName" clearable placeholder="请输入菜单名称"
                    @keyup.enter.native="handleQuery"/>
        </el-form-item>
        <el-form-item label="状态" prop="status">
          <el-radio-group v-model="queryParams.status" @change="handleQuery">
            <el-radio value="">全部</el-radio>
            <el-radio v-for="dict in dictDataMap['sys_normal_disable']" :key="dict.dictValue"
                      :value="dict.dictValue">
              {{
                dict.dictLabel
              }}
            </el-radio>
          </el-radio-group>
        </el-form-item>
        <div class="mr20" style="float: right;">
          <query-form-button @handleQuery="handleQuery" @resetQuery="resetQuery"/>
        </div>
      </el-form>
    </div>
    <el-row :gutter="10" class="mb8">
      <el-col :span="1.5">
        <el-button v-hasPerm="['system:menu:add']" plain type="primary" @click="handleAdd">
          <template #icon>
            <i-ep-plus/>
          </template>
          新增
        </el-button>
      </el-col>
      <el-col :span="1.5">
        <el-button plain type="info" @click="toggleExpandAll">
          <template #icon>
            <i-ep-sort/>
          </template>
          展开/折叠
        </el-button>
      </el-col>
    </el-row>
    <el-table v-if="refreshTable" v-adaptive="36" :border="true" :data="menuList" :default-expand-all="isExpandAll"
              :header-cell-style="$headerCellStyle" :stripe='true'
              :tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
              highlight-current-row row-key="menuId">
      <el-table-column header-:align="'center'" label="菜单名称" prop="menuName"
                       show-overflow-tooltip></el-table-column>
      <el-table-column :align="'center'" label="图标" prop="icon" width="80">
        <template #default="scope">
          <svg-icon :icon-class="scope.row.icon"/>
        </template>
      </el-table-column>
      <el-table-column :align="'center'" label="排序" prop="orderNum" width="60"></el-table-column>
      <el-table-column :align="'center'" label="菜单类型" prop="menuType" show-overflow-tooltip width="110">
        <template #default="scope">
                    <span v-if="scope.row.menuType === 'M'" style="color: #25a608">
                        目录
                    </span>
          <span v-if="scope.row.menuType === 'C'" style="color: #ea0d0d">
                        菜单
                    </span>
          <span v-if="scope.row.menuType === 'F'" style="color: #0d30e8">
                        按钮/功能
                    </span>
        </template>
      </el-table-column>
      <el-table-column header-:align="'center'" label="权限标识" prop="perms"
                       show-overflow-tooltip></el-table-column>
      <el-table-column header-:align="'center'" label="组件路径" prop="component"
                       show-overflow-tooltip></el-table-column>
      <el-table-column header-:align="'center'" label="路由参数" prop="queryParam"
                       show-overflow-tooltip></el-table-column>
      <el-table-column :align="'center'" label="路由地址" prop="path" show-overflow-tooltip
                       width="260"></el-table-column>
      <el-table-column header-:align="'center'" label="是否缓存" prop="v" width="80">
        <template #default="scope">
          <span v-if="scope.row.isCache === '0'" style="color:#2d4cf5;">
            不缓存
          </span>
          <span v-else style="color: #ab0202">
            缓存
          </span>
        </template>
      </el-table-column>
      <el-table-column header-:align="'center'" label="状态" prop="status" width="80">
        <template #default="scope">
          <dict-data-tag :options="dictDataMap['sys_normal_disable']" :value="scope.row.status"/>
        </template>
      </el-table-column>
      <el-table-column :align="'center'" label="创建时间" prop="createTime">
        <template #default="scope">
          <span>{{ $parseTime(scope.row.createTime) }}</span>
        </template>
      </el-table-column>
      <el-table-column :align="'center'" class-name="small-padding fixed-width" label="操作" width="160">
        <template #default="scope">
          <el-tooltip class="item" content="修改"
                      effect="dark"
                      placement="left">
            <el-button circle type="success" @click="handleUpdate(scope.row)">
              <template #icon>
                <i-ep-edit/>
              </template>
            </el-button>
          </el-tooltip>
          <el-tooltip class="item" content="新增"
                      effect="dark"
                      placement="top">
            <el-button circle type="primary" @click="handleAdd(scope.row)">
              <template #icon>
                <i-ep-plus/>
              </template>
            </el-button>
          </el-tooltip>
          <el-tooltip class="item" content="删除"
                      effect="dark"
                      placement="top">
            <el-button circle type="danger" @click="handleDelete(scope.row)">
              <template #icon>
                <i-ep-delete/>
              </template>
            </el-button>
          </el-tooltip>
        </template>
      </el-table-column>
    </el-table>
    <!-- 添加或修改菜单对话框 -->
    <el-dialog v-model="open" :close-on-click-modal="false" :title="title" append-to-body width="40%">
      <el-form ref="formRef" :model="form" :rules="rules" label-width="100px">
        <el-row :gutter="20">
          <el-col :span="24">
            <el-form-item label="上级菜单" prop="parentId">
              <el-tree-select v-model="form.parentId" :data="menuOptions" :render-after-expand="false"
                              check-strictly filterable placeholder="选择上级菜单" style="width: 100%;"/>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="菜单类型" prop="menuType">
              <el-radio-group v-model="form.menuType">
                <el-radio value="M">目录</el-radio>
                <el-radio value="C">菜单</el-radio>
                <el-radio value="F">按钮</el-radio>
              </el-radio-group>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="是否报表" prop="isReport">
              <el-radio-group v-model="form.isReport">
                <el-radio
                  v-for="dict in dictDataMap['sys_yes_no']"
                  :key="dict.dictValue"
                  :border="true"
                  :value="dict.dictValue"
                >{{ dict.dictLabel }}
                </el-radio>
              </el-radio-group>
            </el-form-item>
          </el-col>
          <el-col v-if="form.menuType != 'F'" :span="24">
            <el-form-item label="菜单图标" prop="icon">
              <el-popover :width="460" placement="bottom-start" trigger="click">
                <IconSelect ref="iconSelect" @selected="selected"/>
                <template #reference>
                  <el-input slot="reference" v-model="form.icon" placeholder="点击选择图标" readonly>
                    <template #prepend>
                      <svg-icon slot="prefix" :icon-class="form.icon" class="el-input__icon"
                                style="height: 32px;width: 16px"/>
                    </template>
                  </el-input>
                </template>
              </el-popover>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="菜单名称" prop="menuName">
              <el-input v-model="form.menuName" placeholder="请输入菜单名称"/>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="排序" prop="orderNum">
              <el-input-number v-model="form.orderNum" :min="0" controls-position="right"
                               style="width: 100%;"/>
            </el-form-item>
          </el-col>
          <el-col v-if="form.menuType != 'F'" :span="12">
            <el-form-item prop="isFrame">
              <template #label>
                <div>
                  是否外链
                  <el-tooltip effect="light" placement="bottom">
                    <template #content>选择是外链则路由地址需要以`http(s)://`开头
                    </template>
                    <i-ep-QuestionFilled class="inline-block" style="margin-bottom: -3px;"/>
                  </el-tooltip>
                </div>
              </template>
              <el-radio-group v-model="form.isFrame">
                <el-radio value="0">是</el-radio>
                <el-radio value="1">否</el-radio>
              </el-radio-group>
            </el-form-item>
          </el-col>
          <el-col v-if="form.menuType != 'F'" :span="12">
            <el-form-item prop="path">
              <template #label>
                <div>
                  路由地址
                  <el-tooltip effect="light" placement="bottom">
                    <template #content>访问的路由地址，如：`user`，如外网地址需内链访问则以`http(s)://`开头
                    </template>
                    <i-ep-QuestionFilled class="inline-block" style="margin-bottom: -3px;"/>
                  </el-tooltip>
                </div>
              </template>
              <el-input v-model="form.path" placeholder="请输入路由地址"/>
            </el-form-item>
          </el-col>
          <el-col v-if="form.menuType == 'C'" :span="12">
            <el-form-item>
              <template #label>
                <div>
                  组件路径
                  <el-tooltip effect="light" placement="bottom">
                    <template #content>访问的组件路径，如：`system/user/index`，默认在`views`目录下
                    </template>
                    <i-ep-QuestionFilled class="inline-block" style="margin-bottom: -3px;"/>
                  </el-tooltip>
                </div>
              </template>
              <el-input v-model="form.component" placeholder="system/user/index" style="width: 100%">
                <template #prepend>src/views/</template>
                <template #append>.vue</template>
              </el-input>
            </el-form-item>
          </el-col>
          <el-col v-if="form.menuType != 'M'" :span="12">
            <el-form-item prop="perms">
              <template #label>
                <div>
                  权限字符
                  <el-tooltip effect="light" placement="bottom">
                    <template #content>控制器中定义的权限字符，如：@SaCheckPermission('system:user:list')
                    </template>
                    <i-ep-QuestionFilled class="inline-block" style="margin-bottom: -3px;"/>
                  </el-tooltip>
                </div>
              </template>

              <el-input v-model="form.perms" maxlength="100" placeholder="请输入权限标识"/>
            </el-form-item>
          </el-col>
          <el-col v-if="form.menuType != 'M'" :span="12">
            <el-form-item prop="queryParams">
              <template #label>
                <div>
                  路由参数
                  <el-tooltip effect="light" placement="bottom">
                    <template #content>访问路由的默认传递参数，如：`{"id": 1, "name": "ry"}`
                    </template>
                    <i-ep-QuestionFilled class="inline-block" style="margin-bottom: -3px;"/>
                  </el-tooltip>
                </div>
              </template>

              <el-input v-model="form.queryParam" maxlength="255" placeholder="请输入路由参数"/>
            </el-form-item>
          </el-col>
          <el-col v-if="form.menuType == 'C'" :span="12">
            <el-form-item prop="isCache">
              <template #label>
                <div>
                  是否缓存
                  <el-tooltip effect="light" placement="bottom">
                    <template #content>选择是则会被`keep-alive`缓存，需要匹配组件的`name`和地址保持一致
                    </template>
                    <i-ep-QuestionFilled class="inline-block" style="margin-bottom: -3px;"/>
                  </el-tooltip>
                </div>
              </template>

              <el-radio-group v-model="form.isCache">
                <el-radio label="0">缓存</el-radio>
                <el-radio label="1">不缓存</el-radio>
              </el-radio-group>
            </el-form-item>
          </el-col>
          <el-col v-if="form.menuType != 'F'" :span="12">
            <el-form-item prop="visible">
              <template #label>
                <div>
                  显示状态
                  <el-tooltip effect="light" placement="bottom">
                    <template #content>选择隐藏则路由将不会出现在侧边栏，但仍然可以访问
                    </template>
                    <i-ep-QuestionFilled class="inline-block" style="margin-bottom: -3px;"/>
                  </el-tooltip>
                </div>
              </template>

              <el-radio-group v-model="form.visible">
                <el-radio v-for="dict in dictDataMap['sys_show_hide']" :key="dict.dictValue"
                          :label="dict.dictValue">{{
                    dict.dictLabel
                  }}
                </el-radio>
              </el-radio-group>
            </el-form-item>
          </el-col>
          <el-col v-if="form.menuType != 'F'" :span="12">
            <el-form-item prop="status">
              <template #label>
                <div>
                  启用状态
                  <el-tooltip effect="light" placement="bottom">
                    <template #content>选择停用则路由将不会出现在侧边栏，也不能被访问
                    </template>
                    <i-ep-QuestionFilled class="inline-block" style="margin-bottom: -3px;"/>
                  </el-tooltip>
                </div>
              </template>
              <el-radio-group v-model="form.status">
                <el-radio v-for="dict in dictDataMap['sys_normal_disable']" :key="dict.dictValue"
                          :label="dict.dictValue">{{
                    dict.dictLabel
                  }}
                </el-radio>
              </el-radio-group>
            </el-form-item>
          </el-col>
        </el-row>
      </el-form>
      <template #footer>
                <span class="dialog-footer">
                    <el-button type="primary" @click="submitForm">确 定</el-button>
                    <el-button @click="cancel">取 消</el-button>
                </span>
      </template>
    </el-dialog>
  </div>
</template>

<script lang="ts" setup>
import {addMenu, delMenu, getMenu, listMenu, updateMenu} from "@/api/system/menu"
// import IconSelect from "@/components/IconSelect/tabIndex.vue"
import {useDictStoreHook} from "@/store/modules/dict";

const {proxy} = getCurrentInstance() as any
const dictStore = useDictStoreHook()
const formRef = ref()
const queryForm = ref()

const dictDataMap = ref(dictStore.isTypeGetData('sys_normal_disable', 'sys_show_hide', 'sys_yes_no'))

// 显示搜索条件
const showSearch = ref(true)
// 菜单表格树数据
const menuList = ref([])
// 菜单树选项
const menuOptions = ref<OptionType[]>([]);
// 弹出层标题
const title = ref("")
// 是否显示弹出层
const open = ref(false)
// 是否展开，默认全部折叠
const isExpandAll = ref(false)
// 重新渲染表格状态
const refreshTable = ref(true)
// 查询参数
const queryParams = ref<QueryParamsType>({
  menuName: "",
  visible: "",
  status: '',
  menuTypeArr: []
})
// 表单参数
const form = ref<MenuForm>({
  parentId: 0,
  visible: "1",
  orderNum: 1,
  menuType: 'M',
  isCache: "0",
  status: "0",
  queryParam: '',
  //是否报表 Y是 ；N否
  isReport: "N"
})

// 表单校验
const rules = reactive({
  menuName: [
    {required: true, message: "菜单名称不能为空", trigger: "blur"}
  ],
  orderNum: [
    {required: true, message: "菜单顺序不能为空", trigger: "blur"}
  ],
  path: [
    {required: true, message: "路由地址不能为空", trigger: "blur"}
  ]
})


onMounted(() => {
  getList()
})

// 选择图标
const selected = ((name) => {
  form.value.icon = name
})

/** 查询菜单列表 */
const getList = (() => {
  listMenu(queryParams.value).then(response => {
    nextTick(() =>
      // @ts-ignore
      menuList.value = proxy.$handleTree(response.data, "menuId", "menuName")
    )
  })
})

/** 转换菜单数据结构 */
const normalizer = ((node) => {
  if (node.children && !node.children.length) {
    delete node.children
  }
  return {
    id: node.menuId,
    label: node.menuName,
    children: node.children
  }
})

/** 查询菜单下拉树结构 */
const getTreeselect = (() => {
  listMenu({menuTypeArr: ['M', 'C']}).then(response => {
    menuOptions.value = [{
      value: 0,
      label: "顶级菜单",
      children: proxy.$handleTree(response.data, "menuId", "menuName")
    }];
  })
})

// 取消按钮
const cancel = (() => {
  open.value = false
  reset()
})
// 表单重置
const reset = (() => {
  form.value = {
    menuId: "",
    parentId: 0,
    menuName: undefined,
    icon: undefined,
    menuType: "M",
    orderNum: 0,
    isFrame: "1",
    isCache: "0",
    visible: "0",
    status: "0",
    queryParam: "",
    isReport: "N"
  }
  // proxy.$resetForm("formRef")
})


/** 搜索按钮操作 */
const handleQuery = (() => {
  getList()
})
/** 重置按钮操作 */
const resetQuery = ((form) => {
  proxy.$resetForm(form)
  handleQuery()
})
/** 新增按钮操作 */
const handleAdd = ((row) => {
  reset()
  getTreeselect()
  if (row != null && row.menuId) {
    form.value.parentId = row.menuId
  } else {
    form.value.parentId = 0
  }
  open.value = true
  title.value = "添加菜单"
})
/** 展开/折叠操作 */
const toggleExpandAll = (() => {
  refreshTable.value = false
  isExpandAll.value = !isExpandAll.value
  nextTick(() => {
    refreshTable.value = true
  })
})
/** 修改按钮操作 */
const handleUpdate = ((row: any) => {
  reset()
  getTreeselect()
  getMenu(row.menuId).then(response => {
    form.value = response.data
    open.value = true
    title.value = "修改菜单"
  })
})
/** 提交按钮 */
const submitForm = (() => {
  (formRef.value as any).validate((valid: any) => {
    if (valid) {
      if (form.value.menuId) {
        updateMenu(form.value).then(() => {
          ElMessage.success("修改成功")
          open.value = false
          getList()
        })
      } else {
        addMenu(form.value).then(() => {
          ElMessage.success("新增成功")
          open.value = false
          getList()
        })
      }
    }
  })
})
/** 删除按钮操作 */
const handleDelete = ((row) => {
  ElMessageBox.confirm('是否删除选中的数据项？', '提示', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning'
  }).then(() => {
    delMenu(row.menuId).then(() => {
      getList()
    })
  }).catch(() => {
    getList()
    ElMessage.success('删除失败')
  });
})
</script>
<script lang="ts">
export default {
  name: "Menu"
}
</script>


<style lang="scss" scoped>
.svg-icon {
  fill: #606266
}
</style>
